home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / 8255ppi.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  8KB  |  277 lines

  1. /* INTEL 8255 PPI I/O chip */
  2.  
  3.  
  4. /* NOTE: When port is input,  then data present on the ports
  5.   outputs is 0x0ff */
  6.  
  7. /* KT 10/01/2000 - Added bit set/reset feature for control port */
  8. /*               - Added more accurate port i/o data handling */
  9. /*               - Added output reset when control mode is programmed */
  10.  
  11.  
  12.  
  13. #include "driver.h"
  14. #include "machine/8255ppi.h"
  15.  
  16. static ppi8255_interface    *intf; /* local copy of the intf */
  17.  
  18. typedef struct {
  19.     int        groupA_mode;
  20.     int        groupB_mode;
  21.         /* input output status */
  22.     int        io[3];
  23.         /* data written to ports */
  24.     int        latch[3];
  25.         /* control */
  26.         int        control;
  27. } ppi8255;
  28.  
  29. static ppi8255 chips[MAX_8255];
  30.  
  31. void ppi8255_init( ppi8255_interface *intfce ) {
  32.     int i;
  33.  
  34.     intf = intfce; /* keep a local pointer to the interface */
  35.  
  36.  
  37.     for ( i = 0; i < intf->num; i++ ) {
  38.         chips[i].groupA_mode = 0; /* group a mode */
  39.         chips[i].groupB_mode = 0; /* group b mode */
  40.         chips[i].io[0] = 0xff; /* all inputs */
  41.         chips[i].io[1] = 0xff; /* all inputs */
  42.         chips[i].io[2] = 0xff; /* all inputs */
  43.         chips[i].latch[0] = 0x00; /* clear latch */
  44.         chips[i].latch[1] = 0x00; /* clear latch */
  45.         chips[i].latch[2] = 0x00; /* clear latch */
  46.         chips[i].control = 0x1b;
  47.     }
  48. }
  49.  
  50. int ppi8255_r( int which, int offset ) {
  51.     ppi8255        *chip;
  52.  
  53.     /* Some bounds checking */
  54.     if ( which > intf->num ) {
  55.         logerror("Attempting to read an unmapped 8255 chip\n" );
  56.         return 0;
  57.     }
  58.  
  59.     if ( offset > 3 ) {
  60.         logerror("Attempting to read an invalid 8255 register\n" );
  61.         return 0;
  62.     }
  63.  
  64.     chip = &chips[which];
  65.  
  66.  
  67.     switch( offset )
  68.         {
  69.         case 0: /* Port A read */
  70.             if ( chip->io[0] == 0 )
  71.                         {
  72.                                 /* output */
  73.                 return chip->latch[0];
  74.                         }
  75.                         else
  76.                         {
  77.                                 /* input */
  78.                 if ( intf->portA_r )
  79.                     return (*intf->portA_r)( which );
  80.             }
  81.         break;
  82.  
  83.                 case 1: /* Port B read */
  84.             if ( chip->io[1] == 0 )
  85.                         {
  86.                                 /* output */
  87.                 return chip->latch[1];
  88.                         }
  89.                         else
  90.                         {
  91.                                 /* input */
  92.                 if ( intf->portB_r )
  93.                     return (*intf->portB_r)( which );
  94.             }
  95.         break;
  96.  
  97.         case 2: /* Port C read */
  98.                 {
  99.                         int input = 0;
  100.  
  101.                         /* read data */
  102.                         if (intf->portC_r)
  103.                                 input = (*intf->portC_r)(which);
  104.  
  105.                         /* return data - combination of input and latched output depending on
  106.                         the input/output status of each half of port C */
  107.                         return ((chip->latch[2] & ~chip->io[2]) | (input & chip->io[2]));
  108.                 }
  109.  
  110.         case 3: /* Control word */
  111.                         return 0x0ff;
  112.  
  113.                         //return chip->control;
  114.         break;
  115.     }
  116.  
  117.     logerror("8255 chip %d: Port %c is being read but has no handler", which, 'A' + offset );
  118.  
  119.     return 0x00;
  120. }
  121.  
  122. #define PPI8255_PORT_A_WRITE() \
  123. { \
  124.         int write_data; \
  125.   \
  126.         write_data = (chip->latch[0] & ~chip->io[0]) | \
  127.                         (0x0ff & chip->io[0]); \
  128.   \
  129.         if (intf->portA_w) \
  130.              (*intf->portA_w)(which, write_data); \
  131. }
  132.  
  133. #define PPI8255_PORT_B_WRITE() \
  134. { \
  135.         int write_data; \
  136.   \
  137.         write_data = (chip->latch[1] & ~chip->io[1]) | \
  138.                         (0x0ff & chip->io[1]); \
  139.   \
  140.         if (intf->portB_w) \
  141.              (*intf->portB_w)(which, write_data); \
  142. }
  143.  
  144. #define PPI8255_PORT_C_WRITE() \
  145. { \
  146.         int write_data; \
  147.   \
  148.         write_data = (chip->latch[2] & ~chip->io[2]) | \
  149.                         (0x0ff & chip->io[2]); \
  150.   \
  151.         if (intf->portC_w) \
  152.              (*intf->portC_w)(which, write_data); \
  153. }
  154.  
  155. void ppi8255_w( int which, int offset, int data ) {
  156.     ppi8255        *chip;
  157.  
  158.     /* Some bounds checking */
  159.     if ( which > intf->num ) {
  160.         logerror("Attempting to write an unmapped 8255 chip\n" );
  161.         return;
  162.     }
  163.  
  164.     if ( offset > 3 ) {
  165.         logerror("Attempting to write an invalid 8255 register\n" );
  166.         return;
  167.     }
  168.  
  169.     chip = &chips[which];
  170.  
  171.         /* store written data */
  172.         chip->latch[offset] = data;
  173.  
  174.     switch( offset )
  175.         {
  176.                 case 0: /* Port A write */
  177.                 PPI8255_PORT_A_WRITE();
  178.                 return;
  179.  
  180.         case 1: /* Port B write */
  181.                 PPI8255_PORT_B_WRITE();
  182.                 return;
  183.  
  184.         case 2: /* Port C write */
  185.                 PPI8255_PORT_C_WRITE();
  186.                 return;
  187.  
  188.         case 3: /* Control word */
  189.  
  190.             if ( data & 0x80 )
  191.                         {
  192.                         /* mode set */
  193.                         chip->control = data;
  194.  
  195.                         chip->groupA_mode = ( data >> 5 ) & 3;
  196.                         chip->groupB_mode = ( data >> 2 ) & 1;
  197.  
  198.                         if ( chip->groupA_mode != 0 || chip->groupB_mode != 0 ) {
  199.                                 logerror("8255 chip %d: Setting an unsupported mode!\n", which );
  200.                         }
  201.  
  202.                         /* Port A direction */
  203.             if ( data & 0x10 )
  204.                         {
  205.                                 /* input */
  206.                 chip->io[0] = 0xff;
  207.                         }
  208.             else
  209.                         {
  210.                                 /* output */
  211.                                 chip->io[0] = 0x00;
  212.                         }
  213.  
  214.             /* Port B direction */
  215.             if ( data & 0x02 )
  216.                 chip->io[1] = 0xff;
  217.             else
  218.                 chip->io[1] = 0x00;
  219.  
  220.             /* Port C upper direction */
  221.             if ( data & 0x08 )
  222.                 chip->io[2] |= 0xf0;
  223.             else
  224.                 chip->io[2] &= 0x0f;
  225.  
  226.             /* Port C lower direction */
  227.             if ( data & 0x01 )
  228.                 chip->io[2] |= 0x0f;
  229.             else
  230.                 chip->io[2] &= 0xf0;
  231.  
  232.                         /* KT: 25-Dec-99 - 8255 resets latches when mode set */
  233.                         chip->latch[0] = chip->latch[1] = chip->latch[2] = 0;
  234.  
  235.                         PPI8255_PORT_A_WRITE();
  236.                         PPI8255_PORT_B_WRITE();
  237.                         PPI8255_PORT_C_WRITE();
  238.  
  239.                         }
  240.                         else
  241.                         {
  242.                                 /* KT: 25-Dec-99 - Added port C bit set/reset feature */
  243.                                 /* bit set/reset */
  244.                                 int bit;
  245.  
  246.                                 bit = (data>>1) & 0x07;
  247.  
  248.                                 if (data & 1)
  249.                                 {
  250.                                         /* set bit */
  251.                                         chip->latch[2] |= (1<<bit);
  252.                                 }
  253.                                 else
  254.                                 {
  255.                                         /* bit reset */
  256.                                         chip->latch[2] &= ~(1<<bit);
  257.                                 }
  258.  
  259.                                 PPI8255_PORT_C_WRITE();
  260.             }
  261.                         return;
  262.         break;
  263.     }
  264.  
  265.     logerror("8255 chip %d: Port %c is being written to but has no handler", which, 'A' + offset );
  266. }
  267.  
  268. /* Helpers */
  269. READ_HANDLER( ppi8255_0_r ) { return ppi8255_r( 0, offset ); }
  270. READ_HANDLER( ppi8255_1_r ) { return ppi8255_r( 1, offset ); }
  271. READ_HANDLER( ppi8255_2_r ) { return ppi8255_r( 2, offset ); }
  272. READ_HANDLER( ppi8255_3_r ) { return ppi8255_r( 3, offset ); }
  273. WRITE_HANDLER( ppi8255_0_w ) { ppi8255_w( 0, offset, data ); }
  274. WRITE_HANDLER( ppi8255_1_w ) { ppi8255_w( 1, offset, data ); }
  275. WRITE_HANDLER( ppi8255_2_w ) { ppi8255_w( 2, offset, data ); }
  276. WRITE_HANDLER( ppi8255_3_w ) { ppi8255_w( 3, offset, data ); }
  277.